from kaplurk import Plurker
from kaplurk import Message
import kaplurk

from globelabsapi import Sms
from globelabsapi import Mms
import globelabsapi

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
from google.appengine.api import users

import os
from google.appengine.ext.webapp import template

import random
import types

from datetime import datetime


def __append_message__(request_handler, message):
    try:
        messages = request_handler.__getattribute__('kaplurk.messages')
    except AttributeError:
        messages = None
    if not messages:
        messages = []
    if type(message) == types.ListType:
        messages.extend(message)
    else:
        messages.append(message)
    request_handler.__setattr__('kaplurk.messages', messages)
def __append_error__(request_handler, error):
    try:
        errors = request_handler.__getattribute__('kaplurk.errors')
    except AttributeError:
        errors = None
    if not errors:
        errors = []
    if type(error) == types.ListType:
        errors.extend(error)
    else:
        errors.append(error)
    request_handler.__setattr__('kaplurk.errors', errors)
def __message__(request_handler):
    try:
        messages = request_handler.__getattribute__('kaplurk.messages')
    except AttributeError:
        messages = None
    return messages
def __error__(request_handler):
    try:
        errors = request_handler.__getattribute__('kaplurk.errors')
    except AttributeError:
        errors = None
    return errors


def renderPortion(request_handler, partial_html, template_values):
    template_values['content'] = partial_html
    path = os.path.join(os.path.dirname(__file__), 'index.html')
    request_handler.response.out.write(template.render(path, template_values))


class MainPage(webapp.RequestHandler):

    def get(self):
        plurker = None
        current_user = users.get_current_user()
        if current_user:
            logged_in = True
            url = users.create_logout_url(self.request.uri)
            pq = Plurker.all()
            pq.filter('user =', current_user)
            plurker = pq.get()
        else:
            logged_in = False
            url = users.create_login_url(self.request.uri)

        template_values = {
            'plurker': plurker,
            'current_user': current_user,
            'logged_in': logged_in,
            'url': url,
            }

        renderPortion(self, 'main.html', template_values)


class Register(webapp.RequestHandler):

    def get(self):
        current_user = users.get_current_user()
        if not current_user:
            self.redirect('/')
            return

        plurker = None
        if current_user:
            logged_in = True
            url = users.create_logout_url(self.request.uri)
            pq = Plurker.all()
            pq.filter('user =', current_user)
            plurker = pq.get()
        else:
            logged_in = False
            url = users.create_login_url(self.request.uri)

        template_values = {
            'plurker': plurker,
            'current_user': current_user,
            'logged_in': logged_in,
            'url': url,
            'message': __message__(self),
            'error': __error__(self)
            }

        renderPortion(self, 'register.html', template_values)

    def post(self):
        current_user = users.get_current_user()
        if not current_user:
            self.redirect('/')
            return

        mobile_no = self.request.get('mobile_no')
        if mobile_no.startswith('+63'):
            mobile_no = mobile_no.replace('+63', '0')

        pq = Plurker.all()
        pq.filter('user =', current_user)
        plurker = pq.get()
        if not plurker:
            plurker = Plurker(
                              user = current_user,
                              mobile_no = mobile_no,
                              nickname = self.request.get('nickname')
                              )
            plurker.setPassword(self.request.get('password'))
        else:
            plurker.mobile_no = mobile_no
            plurker.nickname = self.request.get('nickname')
            plurker.setPassword(self.request.get('password'))
        try:
            plurker.put()
            __append_message__(self, 'You have successfully registered!')
            self.redirect('/')
        except db.Error():
            __append_error__(self, 'Sorry, we could not complete your registration.  Please try again later.')
            self.get()


class Account(webapp.RequestHandler):

    def get(self):
        current_user = users.get_current_user()
        if not current_user:
            self.redirect('/')
            return

        plurker = None
        if current_user:
            logged_in = True
            url = users.create_logout_url(self.request.uri)
            pq = Plurker.all()
            pq.filter('user =', current_user)
            plurker = pq.get()

        template_values = {
            'plurker': plurker,
            'current_user': current_user,
            'logged_in': logged_in,
            'url': url,
            'message': __message__(self),
            'error': __error__(self)
            }

        renderPortion(self, 'account.html', template_values)

    def post(self):
        current_user = users.get_current_user()
        if not current_user:
            self.redirect('/')
            return

        mobile_no = self.request.get('mobile_no')
        if mobile_no.startswith('+63'):
            mobile_no = mobile_no.replace('+63', '0')

        nickname = self.request.get('nickname')
        password = self.request.get('password')
        if not mobile_no or not nickname or not password:
            errors = []
            if not mobile_no:
                __append_error__(self, 'Mobile no. required')
            if not nickname:
                __append_error__(self, 'Nickname required')
            if not password:
                __append_error__(self, 'Password required')
            self.get()
            return

        pq = Plurker.all()
        pq.filter('user =', current_user)
        plurker = pq.get()
        if not plurker:
            plurker = Plurker(
                              user = current_user,
                              mobile_no = mobile_no,
                              nickname = nickname
                              )
            plurker.setPassword(password)
        else:
            if plurker.nickname != nickname:
                plurker.uid = None
            plurker.mobile_no = mobile_no
            plurker.nickname = nickname
            plurker.setPassword(password)

        if self.request.get('autokarma_enabled'):
            plurker.autokarma_enabled = True

            mq = Message.all()
            mq.filter('plurker =', plurker)
            messages = mq.fetch(100)
            if len(messages) == 0:
                __append_error__(self, 'Your Message Pool is currently empty.  Please add some messages before enabling Automatic Updates.')
                self.get()
                return
        else:
            plurker.autokarma_enabled = False

        try:
            plurker.put()
            __append_message__(self, 'You have successfully updated your account.')
            self.redirect('/account')
        except db.Error():
            __append_error__(self, 'Sorry, we could not save your changes at the moment.  Please try again later.')
            self.get()


def getMessagePool(request_handler):
    current_user = users.get_current_user()
    if not current_user:
        request_handler.redirect('/')
        return

    plurker = None
    current_user = users.get_current_user()
    if current_user:
        logged_in = True
        url = users.create_logout_url(request_handler.request.uri)
        pq = Plurker.all()
        pq.filter('user =', current_user)
        plurker = pq.get()

    messages = None
    if plurker:
        if not plurker.autokarma_allowed:
            request_handler.redirect('/account')
            return
        mq = Message.all()
        mq.filter('plurker =', plurker)
        messages = mq.fetch(100)

    template_values = {
        'plurker': plurker,
        'current_user': current_user,
        'messages': messages,
        'logged_in': logged_in,
        'url': url,
        'message': __message__(request_handler),
        'error': __error__(request_handler)
        }

    renderPortion(request_handler, 'messages.html', template_values)


class MessagePool(webapp.RequestHandler):

    def get(self):
        getMessagePool(self)


class AddMessage(webapp.RequestHandler):

    def get(self):
        self.redirect('/pool')

    def post(self):
        current_user = users.get_current_user()
        if not current_user:
            self.redirect('/')
            return

        content = self.request.get('content')
        if not content:
            __append_error__(self, 'Content required')
            getMessagePool(self)
            return

        pq = Plurker.all()
        pq.filter('user =', current_user)
        plurker = pq.get()
        if not plurker:
            self.redirect('/')
            return
        else:
            message = Message(
                              plurker = plurker,
                              qualifier = self.request.get('qualifier'),
                              content = self.request.get('content'),
                              lang = self.request.get('lang')
                              )

        try:
            message.put()
            __append_message__(self, 'You have successfully added a new message to your Message Pool.')
            self.redirect('/pool')
        except db.Error():
            __append_error__(self, 'Sorry, we could not save your message at the moment.  Please try again later.')
            MessagePool.get(self)


class DeleteMessage(webapp.RequestHandler):

    def get(self):
        self.redirect('/pool')

    def post(self):
        current_user = users.get_current_user()
        if not current_user:
            self.redirect('/')
            return

        keys = self.request.get_all('message')
        if len(keys) == 0:
            __append_error__(self, 'Please select a message to delete.')
            getMessagePool(self)
            return

        try:
            for k in keys:
                m = Message.get(k)
                db.delete(m)
            __append_message__(self, 'You have successfully deleted messages from your Message Pool.')
            self.redirect('/pool')
        except db.Error():
            __append_error__(self, 'Sorry, we could not delete some of your messages.  Please try again later.')
            getMessagePool(self)


class PostMessage(webapp.RequestHandler):

    def get(self):
        current_user = users.get_current_user()
        if not current_user:
            self.redirect('/')
            return

        plurker = None
        if current_user:
            logged_in = True
            url = users.create_logout_url(self.request.uri)
            pq = Plurker.all()
            pq.filter('user =', current_user)
            plurker = pq.get()

        template_values = {
            'plurker': plurker,
            'current_user': current_user,
            'logged_in': logged_in,
            'url': url,
            'message': __message__(self),
            'error': __error__(self)
            }

        renderPortion(self, 'post.html', template_values)

    def post(self):
        current_user = users.get_current_user()
        if not current_user:
            self.redirect('/')
            return

        mobile_no = self.request.get('mobile_no')
        if mobile_no.startswith('+63'):
            mobile_no = mobile_no.replace('+63', '0')

        pq = Plurker.all()
        pq.filter('mobile_no =', mobile_no)
        plurker = pq.get()
        if plurker:
            message = Message(
                              plurker = plurker,
                              qualifier = '',
                              content = self.request.get('message'),
                              lang = 'en'
                              )

            if message:
                try:
                    kaplurk.post(message)
                    __append_message__(self, 'You have successfully posted a message to your Plurk timeline.')
                    self.redirect('/')
                except db.Error():
                    __append_error__(self, 'Sorry, we could not update your Plurk timeline at the moment.  Please try again later.')
                    self.get()


class AutoKarmaLog(db.Model):
    plurker = db.ReferenceProperty(reference_class=Plurker,required=True)
    nickname = db.StringProperty(required=True)
    message = db.StringProperty(required=True)
    posted_at = db.DateTimeProperty()
    logged_at = db.DateTimeProperty(auto_now_add=True)

class KarmaMaintenance(webapp.RequestHandler):

    def get(self):
        pq = Plurker.all()
        pq.filter('autokarma_enabled =', True)
        plurkers = pq.fetch(1000)
        i = -1
        modulo = int( datetime.now().strftime('%I') )
        for plurker in plurkers:
            i += 1
            if (i % 4) == (modulo % 4):
                try:
                    mq = Message.all()
                    mq.filter('plurker =', plurker)
                    messages = mq.fetch(1000)
    
                    rnd = random.randint(0, len(messages)-1)
                    msg = messages[rnd]
                    kaplurk.post(msg)
    
                    AutoKarmaLog(
                           plurker = plurker,
                           nickname = plurker.nickname,
                           message = msg.qualifier + ' ' + msg.content,
                           posted_at = datetime.now()
                           ).put()
                except Exception():
                    pass


class ProcessSms(webapp.RequestHandler):

    def post(self):
        xml = self.request.body
        globe_msg = globelabsapi.parseMessage(xml)
        messageType = globe_msg.messageType
        if messageType:
            messageType = messageType.upper()
        message = None
        if messageType == 'SMS':
            pq = Plurker.all()
            pq.filter('mobile_no =', globe_msg.source)
            plurker = pq.get()
            if plurker:
                message = Message(
                                  plurker = plurker,
                                  qualifier = '',
                                  content = globe_msg.msg,
                                  lang = 'en'
                                  )
        elif globe_msg.messageType == 'MMS':
            # process mms
            a = 0

        if message:
            try:
                kaplurk.post(message)

                SmsLog(
                       plurker = message.plurker,
                       message = message.content,
                       sms_accepted_at = datetime.now()
                       ).put()

                suq = SmsUsage.all()
                suq.filter('plurker =', message.plurker)
                sms_usage = suq.get()
                if not sms_usage:
                    sms_usage = SmsUsage(
                                         plurker = message.plurker
                                         )

                sms_usage.incrementUsage()
            except db.Error():
                pass


class SmsLog(db.Model):
    plurker = db.ReferenceProperty(reference_class=Plurker,required=True)
    message = db.StringProperty(required=True)
    sms_accepted_at = db.DateTimeProperty()
    app_accepted_at = db.DateTimeProperty(auto_now_add=True)

class SmsUsage(db.Model):
    plurker = db.ReferenceProperty(reference_class=Plurker,required=True)
    usage = db.IntegerProperty(default=1)

    def incrementUsage(self):
        self.usage += 1
        self.put()

class ExternalPostMessage(webapp.RequestHandler):

    def get(self):
        mobile_no = self.request.get('mobile_no')
        if mobile_no.startswith('+63'):
            mobile_no = mobile_no.replace('+63', '0')

        content = self.request.get('message')
        timestamp = self.request.get('timestamp')
        sms_accepted_at = None
        if timestamp:
            sms_accepted_at = datetime.fromtimestamp(float( timestamp ))
        else:
            sms_accepted_at = datetime.now()

        pq = Plurker.all()
        pq.filter('mobile_no =', mobile_no)
        plurker = pq.get()
        if plurker:
            message = Message(
                              plurker = plurker,
                              qualifier = '',
                              content = content,
                              lang = 'en'
                              )

            try:
                kaplurk.post(message)

                SmsLog(
                       plurker = plurker,
                       message = content,
                       sms_accepted_at = sms_accepted_at
                       ).put()

                suq = SmsUsage.all()
                suq.filter('plurker =', plurker)
                sms_usage = suq.get()
                if not sms_usage:
                    sms_usage = SmsUsage(
                                         plurker = plurker
                                         )

                sms_usage.incrementUsage()
            except db.Error():
                pass


class ReloadPlurkerData(webapp.RequestHandler):

    def get(self):
        pq = Plurker.all()
        plurkers = pq.fetch(1000)
        for plurker in plurkers:
            if not kaplurk.isEncodedPassword(plurker.password):
                plurker.setPassword(plurker.password)
            plurker.put()


application = webapp.WSGIApplication([('/', MainPage),
                                      ('/register', Register),
                                      ('/post', PostMessage),
                                      ('/km', KarmaMaintenance),
                                      ('/account', Account),
                                      ('/pool', MessagePool),
                                      ('/add_message', AddMessage),
                                      ('/delete_message', DeleteMessage),
                                      ('/sms', ProcessSms),
                                      ('/ext', ExternalPostMessage),
                                      ('/reprop', ReloadPlurkerData)], debug=True)


def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()
